import logging
import random
import re
import threading
import time
from datetime import datetime
from urllib.parse import urlencode

import pytz
import requests
from concurrent.futures import ThreadPoolExecutor
from flask import Flask, jsonify, request
from flask_apscheduler import APScheduler
from loccommon import mysql_operate
from loccommon.mysql_operate import MysqlDb
from config.flask_config import Config

import os

tz = pytz.timezone('Asia/Shanghai')
now = datetime.now(tz)
print(now)

app = Flask(__name__)

# 创建线程池
executor = ThreadPoolExecutor(max_workers=40)
logging.basicConfig(filename='app.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

db_dynamic = None


def scheduled_task():
    print(f"定时任务执行中...{int(time.time())}")
    data = getEnd0PythonInfo()
    global db_dynamic
    urls = ['http://121.37.220.252:8408/agent/BotChatCompletionsExampleOne',
            'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV2',
            'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV3',
            'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV4'
            ]
    urlsKey = 0
    if data:
        pythoInfo = data[0]
        if pythoInfo["end"] == 1:
            print("无需执行任务")
        else:
            db_dynamic = MysqlDb(pythoInfo['db_host'], pythoInfo['db_port'], pythoInfo['db_user'],
                                 pythoInfo['db_password'],
                                 pythoInfo['db_name'])
            sql = "SELECT * FROM `zbp_keywords` where `id`=%s limit 1"
            keywords_list = db_dynamic.select_db(sql, (pythoInfo['keyword_id']))
            if keywords_list:
                keywords_info = keywords_list[0]
                Threads = 0
                keywords_list = keywords_info['keywords'].split()
                savePyImplementById(pythoInfo['id'], 1)
                print(f"keywords数量{len(keywords_list)}")
                # for keyword in keywords_list:
                #     future = executor.submit(run_task, f'开始线程{Threads}', urls[urlsKey], keyword, pythoInfo)
                #     future.done()
                #     urlsKey += 1
                #     Threads += 1
                #     if urlsKey >= 4:
                #         urlsKey = 0
                #     if Threads >= 40:
                #         Threads = 0
            else:
                print("未找到关键词")
    else:
        print("未找到需要执行的任务")

    scheduler.remove_job("job1")


def scheduled_task_two():
    cronList = getPyCronList()
    timeout_seconds = 20
    now_time = int(time.time())
    print(f"随机任务执行:{now_time}")
    # try:
    #     if not cronList:
    #         return False
    #     for cron in cronList:
    #         if cron['last_execution_time'] is None:
    #             cron['last_execution_time'] = 0
    #         last_time = now_time - int(cron['last_execution_time'])
    #         if int(cron['start_time']) > last_time:
    #             continue
    #         if int(cron['start_time']) == int(cron['end_time']) and int(cron['end_time']) > 0:
    #             requests.get(cron['link'], timeout=timeout_seconds)
    #             savePyCron(cron['id'])
    #             continue
    #         if last_time > int(cron['end_time']):
    #             requests.get(cron['link'], timeout=timeout_seconds)
    #             savePyCron(cron['id'])
    #             continue
    #         new_pn = random.randint(1, 10)
    #         if new_pn > 5:
    #             requests.get(cron['link'], timeout=timeout_seconds)
    #             savePyCron(cron['id'])
    # except Exception as e:
    #     print(e)


@app.route('/test', methods=['GET'])
def test():
    global db_dynamic
    # urlsKey = 0
    # urls = ['http://121.37.220.252:8408/agent/BotChatCompletionsExampleOne',
    #         'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV2',
    #         'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV3',
    #         'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV4'
    #         ]
    # keywords = "腾讯游戏官方网交易账号 火影忍者ol游戏交易 正其仙游戏交易网 游戏交易投保是骗局吗 交易的游戏股评去哪儿了 天龙游戏玩家交易记录 取消游戏币交易吗 游戏王md账号交易 游戏交易员面试问题 游戏币可以交易图 转转游戏交易售后有多久 沙盒游戏能自由交易 哪种游戏币可以交易"
    # keywords_list = keywords.split()
    # for keyword in keywords_list:
    #     print(f"urlsKey:{urlsKey}")
    #     print("urls:"+urls[urlsKey])
    #     urlsKey += 1
    #     if urlsKey >= 3:
    #         urlsKey = 0

    # data = getLastPythonInfo("web1")
    # pythoInfo = data[0]
    # db_dynamic = MysqlDb(pythoInfo['db_host'], pythoInfo['db_port'], pythoInfo['db_user'],
    #                              pythoInfo['db_password'],
    #                              pythoInfo['db_name'])
    # log_CateID = 1
    # # scheduled_task_two()
    # log_CreateTime = int(time.time())
    # log_PostTime = log_UpdateTime = int(time.time())
    # log_CateID = log_CateID
    # log_AuthorID = 1
    # log_Tag = ""
    # log_Type = 0
    # log_Alias = ""
    # log_Meta = ""
    # log_Template = ""
    # log_Title = "和平精英买号价格标准全攻略 如何挑选性价比高的账号？"
    # log_Content = '<p>导读：如今，可交易游戏币的麻将手游成为了众多玩家的心头好。这类手游不仅带来了传统麻将的乐趣，还能让玩家通过交易游戏币获取额外的收益。本攻略将带你深入了解这类手游，助你在游戏中畅游。</p><p>一、游戏介绍</p><p>1. 介绍游戏的背景、玩法规则等基本信息。</p><p>2. 强调游戏中可交易游戏币的特点。</p><p>二、获取游戏币的途径</p><p>1. 日常任务奖励。</p><p>2. 参加赛事获得。</p><p>3. 与其他玩家进行互动。</p><p>三、交易流程<center><img src="https://img0.baidu.com/it/u=2895231149,650516819&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500" alt="全面解析"/></center></p><p>1. 找到合适的交易平台或渠道。</p><p>2. 了解交易规则和手续费。</p><p>3. 安全交易的注意事项。</p><p>四、提升游戏币价值的方法</p><p>1. 提升自身游戏技巧。</p><p>2. 组建强大的团队。</p><p>3. 参与游戏活动。</p><p>五、交易风险与防范</p><p>1. 避免与陌生玩家进行交易。</p><p>2. 注意交易信息的真实性。</p><p>3. 及时处理交易纠纷。</p><p>内容总结：通过了解可交易游戏币的麻将手游的特点和交易流程，玩家可以更好地在游戏中获取和利用游戏币，实现财富的积累。</p><p>1. 麻将手游官方网站。</p><p>2. 相关游戏论坛。</p><p>3. 专业游戏交易平台介绍。</p>'
    # log_Status = 1
    # log_Intro = "<p>一、价格影响因素</p><p>1. 等级：等级越高，账号价格通常越高，因为高等级账号需花费大量时间和精力升级。</p><p>2. 装备：拥有稀有或高级装备的账号价格会更高，如稀有皮肤、高倍镜等。</p><p>3. 信誉：账号信誉度也影响价格，无封禁或违规记录的账号价格相对较高。</p>"
    # sql = "insert into `zbp_post` (`log_CateID`,`log_AuthorID`,`log_Tag`,`log_Type`,`log_Alias`,`log_Template`,`log_Meta`,`log_Status`,`log_Title`,`log_Intro`,`log_Content`,`log_CreateTime`,`log_PostTime`,`log_UpdateTime`) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
    # value = (
    # log_CateID, log_AuthorID, log_Tag, log_Type, log_Alias, log_Template, log_Meta, log_Status, log_Title, log_Intro,
    # log_Content, log_CreateTime, log_PostTime, log_UpdateTime)
    # # lock = threading.Lock()
    # # lock.acquire()
    # result = db_dynamic.execute_db(sql, value)


    # originaltitle = "如何做假游戏账号交易攻略 从入门到实践"
    # utf8_bytes = originaltitle.encode('utf-8')
    # hex_title = utf8_bytes.hex()
    # # hex_string= "59824f55505a50476e38620f8d2653f74ea46613653b7565204ece516595e852305b9e8df5"
    # print(hex_title)
    # decoded_string1 = bytes.fromhex(hex_title).decode('utf-8')
    # print(decoded_string1)

    # info = BaiduPic("王者 v10 号价格及交易平台指南")
    # info = So360Pic("王者 v10 号价格及交易平台指南")
    # try:
    #     middle_url = info['data'][0]['middleURL']
    #     print("middleURL 存在:", middle_url)
    # except (KeyError, IndexError):
    #     print("middleURL 不存在")

    # urls = ['http://121.37.220.252:8408/agent/BotChatCompletionsExampleOne',
    #         'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV2',
    #         'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV3',
    #         'http://121.37.220.252:8408/agent/BotChatCompletionsExampleOneV4']
    #
    # pythoInfo = selectPythonInfo("web1")
    # db_dynamic = MysqlDb(pythoInfo['db_host'], pythoInfo['db_port'], pythoInfo['db_user'], pythoInfo['db_password'],
    #                      pythoInfo['db_name'])
    # info = selectKeyword(pythoInfo['keyword_id'])
    # keywords_list = info['keywords'].split()
    #
    # result = run_task(1, "http://121.37.220.252:8408/agent/BotChatCompletionsExampleOne", keywords_list[0], pythoInfo)
    # print(result)
    response = {
        "status": "success",
        "message": ""
    }
    return jsonify(response)


def run_task(num, url, keywords, pythoInfo):
    logging.info(f"第三方请求开始: {num}")
    print(f"第三方请求开始: {num},关键字-->{keywords}")
    keywords = re.sub(r'\s+', '，', keywords)
    ex_description = "1.生成结构化的攻略 2.文章字数控制在500-800字 3.包含带有《》的标题"
    if pythoInfo["ex_description"]:
        ex_description = pythoInfo["ex_description"]
    data = '{"content": "关键词：' + keywords + ' ' + ex_description + '"}'
    content = post_data(url, data)
    if content is None:
        print(f"未获取到内容的关键字: {keywords}")
        return None
    title_match = re.search(r'《(.*?)》', content)
    body = re.sub(r'《.*?》', '', content).strip()
    body = re.sub(r'^.*?\*\*\*\*', '', body).strip()
    body = re.sub(r'\n+', '</p><p>', body)
    body = '<p>' + body + '</p>'
    match = re.search(r'(.*?)(</p>.*?</p>.*?</p>.*?</p>)', body, re.DOTALL)
    if match:
        log_Intro = match.group(0)
    else:
        log_Intro = body[:210]

    if title_match:
        title = title_match.group(1)

        body = rand_insert_body_pic(title, body, title)
    else:
        title = None
    print(f"保存:{title}")
    if not pythoInfo['category']:
        log_CateID = 1
        print("pythoInfo['category'] 为空")
    else:
        categories = pythoInfo['category'].split(',')
        log_CateID = random.choice(categories)
    saveContent(title, body, log_Intro, pythoInfo, keywords,log_CateID)

    return '任务完成'


def rand_insert_body_pic(title, body, originaltitle=None, not_rand=None, pn=None, for_in=0):
    try:
        print(f"for_in:{for_in}")
        if for_in >= 2:
            utf8_bytes = originaltitle.encode('utf-8')
            hex_title = utf8_bytes.hex()
            img_pic = '<center><img src="/img/' + hex_title + '.jpg" alt="' + originaltitle + '"/></center>'
        else:
            if not pn:
                pn = random.randint(1, 30)
            baiduPicInfo = BaiduPic(title, pn)
            middle_url = baiduPicInfo['data'][0]['middleURL']
            img_pic = '<center><img src="' + middle_url + '" alt="' + title + '"/></center>'
        try:
            br_positions = [m.start() for m in re.finditer(r'</p>', body)]
            total_len = (len(br_positions)) - 1
            chosen_position = random.choice(br_positions[1:total_len])
            new_body = body[:chosen_position] + img_pic + body[chosen_position:]
        except (KeyError, IndexError, Exception):
            new_body = img_pic + body

        if not not_rand:
            if random.randint(0, 1) == 1:
                rand_num = int(baiduPicInfo['displayNum']) - 1
                new_pn = random.randint(1, rand_num)
                if new_pn == pn:
                    new_pn += 1
                new_body = rand_insert_body_pic(title, new_body, originaltitle, True, new_pn, for_in)
        return new_body
    except (KeyError, IndexError, Exception):
        print("插入图片出现错误")
        title = title[:4]
        pn = random.randint(1, 10)
        for_in += 1
        return rand_insert_body_pic(title, body, originaltitle, True, pn, for_in)


def post_data(url, data):
    retries = 3
    while retries > 0:
        try:
            timeout_seconds = 300
            headers = {
                'Accept': '*/*',
                'Authorization': '4e92a3c21aa46fe075f0965d939090b9',
                "Content-Type": "application/json"
            }
            print(f"发送信息--->：url：{url},data:{data}")
            lock = threading.Lock()
            lock.acquire()
            response = requests.post(url, headers=headers, data=data.encode('utf-8'), timeout=timeout_seconds)
            lock.release()
            print(f"返回信息--->：{response.status_code}")

            if response.status_code == 200:
                # 返回第三方接口的数据
                result = response.json()
                if result['code'] == 100 or result['code'] == 200 or result['content'] is None:
                    return result['content']
                else:
                    retries -= 1
                    print(f"请求失败，错误原因{result}，状态码: {response.status_code}")
                    logging.error(f"请求失败，错误原因: {result}")
            else:
                retries -= 1
                print(f"关键词 {data} 请求失败，状态码: {response.status_code}")
                logging.error(f"关键词 {data} 请求失败，状态码: {response.status_code}")
        except requests.exceptions.RequestException as e:
            retries -= 1
            print(f"关键词 {data} 请求失败，状态码: {response.status_code}")
            logging.error(f"关键词 {data} 请求失败，状态码: {e.request.data}")


def startJob():
    print("加入关键字 执行定时计划")
    if not scheduler.get_job("job1"):
        scheduler.add_job(id='job1', func=scheduled_task, trigger='interval', seconds=10)


@app.route('/taskinto', methods=['POST'])
def task_into():
    data = request.json
    up_into = data.get('up_into')
    web_aliases = data.get('web_aliases')
    category = data.get('category')
    global db_dynamic
    try:
        if up_into is None:
            raise Exception("值不能为空")

        up_into = int(up_into)
        pythoInfo = selectPythonInfo(str(web_aliases))
        # 更新为最新值
        db_dynamic = MysqlDb(pythoInfo['db_host'], pythoInfo['db_port'], pythoInfo['db_user'],
                             pythoInfo['db_password'], pythoInfo['db_name'])
        if up_into <= 0:
            sql = "SELECT * FROM zbp_keywords order by id desc limit 1"
            data = db_dynamic.select_db(sql)
            if data:
                latest_record = data[0]
                isSave = savePyImplement(latest_record["id"], web_aliases, latest_record['category'])
                if not isSave:
                    raise Exception("请先配置数据库")
                params = {
                    "subnum": latest_record['subnum'] + 1,
                }
                saveKeyword(latest_record["id"], params)
            else:
                raise Exception("没有最新数据")
        else:
            isSave = savePyImplement(up_into, web_aliases, category)
            if not isSave:
                raise Exception("请先配置数据库。")
            keywordInfo = selectKeyword(up_into)
            params = {
                "subnum": keywordInfo['subnum'] + 1,
            }
            saveKeyword(up_into, params)
        startJob()
        response = {
            "status": "success",
            "message": "Task into endpoint is working!"
        }
        return jsonify(response)
    except Exception as e:
        response = {
            "status": "error",
            "message": str(e)
        }
        return jsonify(response), 500


def selectKeyword(keyword_id):
    sql = "SELECT * FROM zbp_keywords where `id`=%s limit 1"
    data = db_dynamic.select_db(sql, keyword_id)
    return data[0]


def saveKeyword(keyword_id, params):
    global db_dynamic
    update_time = int(time.time())
    db_dynamic.execute_db(
        "update `zbp_keywords` set `updatetime`=%s,`subnum`=%s where `id`=%s",
        (update_time, params['subnum'], keyword_id))
    return True


def selectPythonInfo(web_aliases):
    sql = "SELECT * FROM zbp_py_implement where `web_aliases`=%s order by id desc limit 1"
    data = mysql_operate.db.select_db(sql, (web_aliases))
    if data:
        return data[0]
    else:
        raise Exception("没有最新数据")


def getLastPythonInfo(web_aliases=None):
    aliases = ""
    if web_aliases:
        aliases = 'where `web_aliases`="' + web_aliases + '"'
    sql = "SELECT * FROM zbp_py_implement " + aliases + " order by id desc limit 1"
    data = mysql_operate.db.select_db(sql)
    return data


def getEnd0PythonInfo():
    sql = "SELECT * FROM zbp_py_implement where `end`=0 order by id desc limit 1"
    data = mysql_operate.db.select_db(sql)
    return data


def getPyCronList():
    sql = "SELECT * FROM zbp_py_cron"
    data = mysql_operate.db.select_db(sql)
    return data


def savePyCron(id):
    last_execution_time = int(time.time())
    mysql_operate.db.execute_db("update `zbp_py_cron` set `last_execution_time`=%s where `id`=%s",
                                (last_execution_time, id))


def saveContent(title, body, log_Intro, pythoInfo,keywords, log_CateID=1):
    global db_dynamic
    db_dynamic = MysqlDb(pythoInfo['db_host'], pythoInfo['db_port'], pythoInfo['db_user'],
                         pythoInfo['db_password'],
                         pythoInfo['db_name'])
    if title is None:
        print(f"插入失败关键字: {keywords}")
        logging.error(f"插入失败关键字: {keywords}")
        return False
    log_Status = 1
    log_CreateTime = int(time.time())
    log_PostTime = log_UpdateTime = int(time.time())
    log_CateID = log_CateID
    log_AuthorID = 1
    log_Tag = ""
    log_Type = 0
    log_Alias = ""
    log_Meta = ""
    log_Template = ""
    log_Title = title
    log_Content = body
    sql = "insert into `zbp_post` (`log_CateID`,`log_AuthorID`,`log_Tag`,`log_Type`,`log_Alias`,`log_Template`,`log_Meta`,`log_Status`,`log_Title`,`log_Intro`,`log_Content`,`log_CreateTime`,`log_PostTime`,`log_UpdateTime`) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
    value = (log_CateID, log_AuthorID, log_Tag, log_Type, log_Alias, log_Template, log_Meta, log_Status, log_Title,log_Intro,log_Content, log_CreateTime, log_PostTime, log_UpdateTime)
    result = db_dynamic.execute_db(sql, value)
    print(f"插入的关键字{keywords}处理状态：{result}")
    logging.info(f"插入的关键字{keywords}处理状态：{result}")


def savePyImplement(keyword_id, web_aliases, category=1, end=0):
    data = getLastPythonInfo(web_aliases)
    update_time = int(time.time())
    if data:
        latest_record = data[0]
        mysql_operate.db.execute_db(
            "update `zbp_py_implement` set `keyword_id`=%s,`updatetime`=%s,`end`=%s,`category`=%s where `id`=%s",
            (keyword_id, update_time, end, category, latest_record['id']))
        return True
    else:
        return False


def savePyImplementById(id, end=0):
    update_time = int(time.time())
    mysql_operate.db.execute_db(
        "update `zbp_py_implement` set `updatetime`=%s,`end`=%s where `id`=%s",
        (update_time, end, id))
    return True

def savePyImPlementParams(id,params):
    update_time = int(time.time())
    mysql_operate.db.execute_db()

def So360Pic(keyword):
    url = 'https://image.so.com/j'
    timestamp_ms = int(time.time() * 1000)
    pass


def BaiduPic(keyword, pn):
    url = 'https://image.baidu.com/search/acjson'
    timestamp_ms = int(time.time() * 1000)
    word = keyword
    queryWord = keyword
    params = setBaiduPicParam(pn, word, queryWord, timestamp_ms)
    info = getFor(url, params)
    return info


def getFor(url, params=None):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
        'Content-Type': 'application/json',
        'Accept': '*/*',
        'Host': 'image.baidu.com',
        'Connection': 'keep-alive',
        'Cookie': ''
    }
    payload = urlencode(params)
    response = requests.get(url=url + "?" + payload, headers=headers)
    if response.status_code == 200:
        return response.json()


def setBaiduPicParam(pn, word, queryWord, timestamp_ms):
    return {
        "tn": "resulttagjson",
        "logid": "",
        "ie": "utf-8",
        "fr": "",
        "word": word,
        "ipn": "r",
        "fm": "index",
        "pos": "history",
        "queryWord": queryWord,
        "cl": 2,
        "lm": -1,
        "oe": "utf-8",
        "adpicid": "",
        "st": -1,
        "z": "",
        "ic": "",
        "hd": 1,
        "latest": "",
        "copyright": "",
        "s": "",
        "se": "",
        "tab": "",
        "width": 1920,
        "height": 1080,
        "face": 0,
        "istype": 2,
        "qc": "",
        "nc": 1,
        "expermode": "",
        "nojc": "",
        "isAsync": True,
        "pn": pn,
        "rn": 1,
        "gsm": "1e",
        timestamp_ms: ""
    }


if __name__ == '__main__':
    app.config.from_object(Config)

    scheduler = APScheduler()
    scheduler.init_app(app)
    scheduler.start()

    app.run(debug=True, use_reloader=False, port=11080, host='0.0.0.0')
